﻿#light

// "Target"
type Compound(name: string) =
    let mutable boilingPoint = 0.0f
    let mutable meltingPoint = 0.0f
    let mutable molecularWeight = 0.0
    let mutable molecularFormula = ""

    member this.BoilingPoint with get() = boilingPoint
                             and set v = boilingPoint <- v

    member this.MeltingPoint with get() = meltingPoint
                             and set v = meltingPoint <- v

    member this.MolecularWeight with get() = molecularWeight
                                and set v = molecularWeight <- v

    member this.MolecularFormula with get() = molecularFormula
                                 and set v = molecularFormula <- v

    abstract Display : unit -> unit
    default this.Display() =
        printfn "\nCompound: %s ------ " name

// "Adaptee"
type ChemicalDatabank() =

    // The Databank 'legacy API'
    member this.GetCriticalPoint(compound: string, point) =
        if point = "M"
            then match compound.ToLower() with // Melting Point
                    | "water"   -> 0.0f
                    | "benzene" -> 5.5f
                    | "alcohol" -> -114.1f
                    | _         -> failwith "unknown compound"
            else match compound.ToLower() with // Boiling Point
                    | "water"   -> 100.0f
                    | "benzene" -> 80.1f
                    | "alcohol" -> 78.3f
                    | _         -> failwith "unknown compound"

    member this.GetMolecularStructure(compound: string) =
        match compound.ToLower() with
            | "water"   -> "H20"
            | "benzene" -> "C6H6"
            | "alcohol" -> "C2H6O2"
            | _         -> failwith "unknown compound"

    member this.GetMolecularWeight(compound: string) =
        match compound.ToLower() with
            | "water"   -> 18.015
            | "benzene" -> 78.1134
            | "alcohol" -> 46.0688
            | _         -> failwith "unknown compound"
    
// "Adapter"
type RichCompound(name: string, bank: ChemicalDatabank) as this =
    inherit Compound(name)
    
    do this.BoilingPoint <- bank.GetCriticalPoint(name, "B")
    do this.MeltingPoint <- bank.GetCriticalPoint(name, "M")
    do this.MolecularWeight <- bank.GetMolecularWeight(name)
    do this.MolecularFormula <- bank.GetMolecularStructure(name)
    
    override this.Display() =
        // Adaptee
        base.Display()
        printfn " Formula: %s" this.MolecularFormula
        printfn " Weight : %f" this.MolecularWeight
        printfn " Melting Pt: %f" this.MeltingPoint
        printfn " Boiling Pt: %f" this.BoilingPoint

    new(name) =
        RichCompound(name, ChemicalDatabank())
